home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / game / wins1726.zip / FPU087.ASM < prev    next >
Assembly Source File  |  1991-09-03  |  37KB  |  1,488 lines

  1. TITLE fpu087.asm (C) 1989, Mark C. Peterson, CompuServe [70441,3353]
  2. SUBTTL All rights reserved.
  3. ;
  4. ;  Code may be used in any program provided the author is credited
  5. ;    either during program execution or in the documentation.  Source
  6. ;    code may be distributed only in combination with public domain or
  7. ;    shareware source code.  Source code may be modified provided the
  8. ;    copyright notice and this message is left unchanged and all
  9. ;    modifications are clearly documented.
  10. ;
  11. ;    I would appreciate a copy of any work which incorporates this code.
  12. ;
  13. ;    Mark C. Peterson
  14. ;    405-C Queen St., Suite #181
  15. ;    Southington, CT 06489
  16. ;    (203) 276-9721
  17. ;
  18. ;  References:
  19. ;     The VNR Concise Encyclopedia of Mathematics
  20. ;        by W. Gellert, H. Hustner, M. Hellwich, and H. Kastner
  21. ;        Published by Van Nostrand Reinhold Comp, 1975
  22. ;
  23. ;     80386/80286 Assembly Language Programming
  24. ;        by William H. Murray, III and Chris H. Pappas
  25. ;        Published by Osborne McGraw-Hill, 1986
  26. ;
  27. ;  History since Fractint 16.3:
  28. ;     CJLT changed e2x and Log086 algorithms for more speed
  29. ;     CJLT corrected SinCos086 for -ve angles in 2nd and 4th quadrants
  30. ;     CJLT speeded up SinCos086 for angles >45 degrees in any quadrant
  31. ;     (See comments containing the string `CJLT')
  32. ; 14 Aug 91 CJLT removed r16Mul - not called from anywhere
  33. ; 21 Aug 91 CJLT corrected Table[1] from 6 to b
  34. ;                improved bx factors in Log086 for more accuracy
  35. ;                corrected Exp086 overflow detection to 15 from 16 bits.
  36. ;
  37. ; CJLT=      Chris J Lusby Taylor
  38. ;            32 Turnpike Road
  39. ;            Newbury, England (where's that?)
  40. ;        Contactable via Compuserve user Stan Chelchowski [100016,351]
  41. ;                     or Tel 011 44 635 33270 (home)
  42. ;
  43. ;
  44. ;PROCs in this module:
  45. ;FPUcplxmul     PROC     x:word, y:word, z:word
  46. ;FPUcplxdiv     PROC     x:word, y:word, z:word
  47. ;FPUcplxlog     PROC     x:word, z:word
  48. ;FPUsinhcosh    PROC     x:word, sinh:word, cosh:word
  49. ;FPUsincos  PROC  x:word, sinx:word, cosx:word
  50. ;r16Mul     PROC    uses si di, x1:word, x2:word, y1:word, y2:word
  51. ;RegFloat2Fg     PROC    x1:word, x2:word, Fudge:word
  52. ;RegFg2Float     PROC   x1:word, x2:word, FudgeFact:byte
  53. ;ExpFudged      PROC    uses si, x_low:word, x_high:word, Fudge:word
  54. ;LogFudged      PROC    uses si di, x_low:word, x_high:word, Fudge:word
  55. ;LogFloat14     PROC     x1:word, x2:word
  56. ;RegSftFloat     PROC   x1:word, x2:word, Shift:byte
  57. ;RegDivFloat     PROC  uses si di, x1:word, x2:word, y1:word, y2:word
  58. ;SinCos086   PROC     uses si di, LoNum:WORD, HiNum:WORD, SinAddr:WORD, \
  59. ;_e2xLT   PROC        ;argument in dx.ax (bitshift=16 is hard coded here)
  60. ;Exp086    PROC     uses si di, LoNum:WORD, HiNum:WORD
  61. ;SinhCosh086    PROC     uses si di, LoNum:WORD, HiNum:WORD, SinhAddr:WORD, \
  62. ;Log086   PROC     uses si di, LoNum:WORD, HiNum:WORD, Fudge:WORD
  63.  
  64.  
  65. IFDEF ??version
  66. MASM51
  67. QUIRKS
  68. EMUL
  69. ENDIF
  70.  
  71. .model medium, c
  72.  
  73. extrn cos:far
  74. extrn _Loaded387sincos:far
  75. extrn compiled_by_turboc:word
  76.  
  77.  
  78. .data
  79.  
  80. extrn cpu:WORD
  81.  
  82. PUBLIC TrigLimit, TrigOverflow
  83.  
  84. PiFg13         dw       6487h
  85. InvPiFg33      dd       0a2f9836eh
  86. InvPiFg16      dw       517ch
  87. Ln2Fg16        dw       0b172h ;ln(2) * 2^16 . True value is b172.18
  88. Ln2Fg15        dw       058b9h ;used by e2xLT. True value is 58b9.0C
  89. TrigOverflow   dw       0
  90. TrigLimit      dd       0
  91. ;
  92. ;Table of 2^(n/16) for n=0 to 15. All entries fg15.
  93. ;Used by e2xLT
  94. Table        dw    08000h,085abh,08b96h,091c4h
  95.         dw    09838h,09ef5h,0a5ffh,0ad58h
  96.         dw    0b505h,0bd09h,0c567h,0ce25h
  97.         dw    0d745h,0e0cdh,0eac1h,0f525h
  98. one            dw       ?
  99. expSign        dw       ?
  100. a              dw       ?
  101. SinNeg         dw       ?    ;CJLT - not now needed by SinCos086, but by
  102. CosNeg           dw    ?    ;       ArcTan086
  103. Ans           dq    ?
  104. fake_es        dw       ?         ; <BDT> Windows can't use ES for storage
  105.  
  106. TaylorTerm  MACRO
  107. LOCAL Ratio
  108.    add   Factorial, one
  109.    jnc   SHORT Ratio
  110.  
  111.    rcr   Factorial, 1
  112.    shr   Num, 1
  113.    shr   one, 1
  114.  
  115. Ratio:
  116.    mul   Num
  117.    div   Factorial
  118. ENDM
  119.  
  120.  
  121.  
  122. _4_         dq    4.0
  123. _2_         dq    2.0
  124. _1_         dq    1.0
  125. PointFive   dq    0.5
  126. temp        dq     ?
  127. Sign        dw     ?
  128.  
  129. extrn fpu:word
  130.  
  131. .code
  132.  
  133.  
  134. FPUcplxmul     PROC     x:word, y:word, z:word
  135.    mov   bx, x
  136.    fld   QWORD PTR [bx]       ; x.x
  137.    fld   QWORD PTR [bx+8]     ; x.y, x.x
  138.    mov   bx, y
  139.    fld   QWORD PTR [bx]       ; y.x, x.y, x.x
  140.    fld   QWORD PTR [bx+8]     ; y.y, y.x, x.y, x.x
  141.    mov   bx, z
  142.    fld   st                   ; y.y, y.y, y.x, x.y, x.x
  143.    fmul  st, st(3)            ; y.y*x.y, y.y. y.x, x.y, x.x
  144.    fld   st(2)                ; y.x, y.y*x.y, y.y, y.x, x.y, x.x
  145.    fmul  st, st(5)            ; y.x*x.x, y.y*x.y, y.y, y.x, x.y, x.x
  146.    fsubr                      ; y.x*x.x - y.y*x.y, y.y, y.x, x.y, x.x
  147.    fstp  QWORD PTR [bx]       ; y.y, y.x, x.y, x.x
  148.    fmulp st(3), st            ; y.x, x.y, x.x*y.y
  149.    fmul                       ; y.x*x.y, x.x*y.y
  150.    fadd                       ; y.x*x.y + x.x*y.y
  151.    fstp  QWORD PTR [bx+8]
  152.    ret
  153. FPUcplxmul     ENDP
  154.  
  155.  
  156.  
  157.  
  158.  
  159. FPUcplxdiv     PROC     x:word, y:word, z:word
  160.    mov   bx, x
  161.    fld   QWORD PTR [bx]       ; x.x
  162.    fld   QWORD PTR [bx+8]     ; x.y, x.x
  163.    mov   bx, y
  164.    fld   QWORD PTR [bx]       ; y.x, x.y, x.x
  165.    fld   QWORD PTR [bx+8]     ; y.y, y.x, x.y, x.x
  166.    fld   st                   ; y.y, y.y, y.x, x.y, x.x
  167.    fmul  st, st               ; y.y*y.y, y.y, y.x, x.y, x.x
  168.    fld   st(2)                ; y.x, y.y*y.y, y.y, y.x, x.y, x.x
  169.    fmul  st, st               ; y.x*y.x, y.y*y.y, y.y, y.x, x.y, x.x
  170.    fadd                       ; mod, y.y, y.x, x.y, x.x
  171.    fdiv  st(1), st            ; mod, y.y=y.y/mod, y.x, x.y, x.x
  172.    fdivp st(2), st            ; y.y, y.x=y.x/mod, x.y, x.x
  173.    mov   bx, z
  174.    fld   st                   ; y.y, y.y, y.x, x.y, x.x
  175.    fmul  st, st(3)            ; y.y*x.y, y.y. y.x, x.y, x.x
  176.    fld   st(2)                ; y.x, y.y*x.y, y.y, y.x, x.y, x.x
  177.    fmul  st, st(5)            ; y.x*x.x, y.y*x.y, y.y, y.x, x.y, x.x
  178.    fadd                       ; y.x*x.x - y.y*x.y, y.y, y.x, x.y, x.x
  179.    fstp  QWORD PTR [bx]       ; y.y, y.x, x.y, x.x
  180.    fmulp st(3), st            ; y.x, x.y, x.x*y.y
  181.    fmul                       ; y.x*x.y, x.x*y.y
  182.    fsubr                      ; y.x*x.y + x.x*y.y
  183.    fstp  QWORD PTR [bx+8]
  184.    ret
  185. FPUcplxdiv     ENDP
  186.  
  187.  
  188.  
  189. FPUcplxlog     PROC     x:word, z:word
  190. LOCAL Status:word
  191.    mov   bx, x
  192.    fld   QWORD PTR [bx+8]        ; x.y
  193.    fld   QWORD PTR [bx]          ; x.x, x.y
  194.    mov   bx, z
  195.    fldln2                        ; ln2, x.x, x.y
  196.    fdiv  _2_                     ; ln2/2, x.x, x.y
  197.    fld   st(2)                   ; x.y, ln2/2, x.x, x.y
  198.    fmul  st, st                  ; sqr(x.y), ln2/2, x.x, x.y
  199.    fld   st(2)                   ; x.x, sqr(x.y), ln2/2, x.x, x.y
  200.    fmul  st, st                  ; sqr(x.x), sqr(x.y), ln2/2, x.x, x.y
  201.    fadd                          ; mod, ln2/2, x.x, x.y
  202.    fyl2x                         ; z.x, x.x, x.y
  203.    fstp  QWORD PTR [bx]          ; x.x, x.y
  204.    cmp   fpu, 387
  205.    jne   Restricted
  206.  
  207.    fpatan
  208.    jmp   StoreZX
  209.  
  210. Restricted:
  211.    mov   bx, x
  212.    mov   dh, BYTE PTR [bx+7]
  213.    or    dh, dh
  214.    jns   ChkYSign
  215.  
  216.    fchs                          ; |x.x|, x.y
  217.  
  218. ChkYSign:
  219.    mov   dl, BYTE PTR [bx+8+7]
  220.    or    dl, dl
  221.    jns   ChkMagnitudes
  222.  
  223.    fxch                          ; x.y, |x.x|
  224.    fchs                          ; |x.y|, |x.x|
  225.    fxch                          ; |x.x|, |x.y|
  226.  
  227. ChkMagnitudes:
  228.    fcom  st(1)                   ; x.x, x.y
  229.    fstsw Status                  ; x.x, x.y
  230.    test  Status, 4500h
  231.    jz    XisGTY
  232.  
  233.    test  Status, 4000h
  234.    jz    XneY
  235.  
  236.    fstp  st                      ; x.y
  237.    fstp  st                      ; <empty>
  238.    fldpi                         ; Pi
  239.    fdiv  _4_                     ; Pi/4
  240.    jmp   ChkSignZ
  241.  
  242. XneY:
  243.    fxch                          ; x.y, x.x
  244.    fpatan                        ; Pi/2 - Angle
  245.    fldpi                         ; Pi, Pi/2 - Angle
  246.    fdiv  _2_                     ; Pi/2, Pi/2 - Angle
  247.    fsubr                         ; Angle
  248.    jmp   ChkSignZ
  249.  
  250. XisGTY:
  251.    fpatan
  252.  
  253. ChkSignZ:
  254.    or    dh, dh
  255.    js    NegX
  256.  
  257.    or    dl, dl
  258.    jns   StoreZX
  259.  
  260.    fchs
  261.    jmp   StoreZX
  262.  
  263. NegX:
  264.    or    dl, dl
  265.    js    QuadIII
  266.  
  267.    fldpi
  268.    fsubr
  269.    jmp   StoreZX
  270.  
  271. QuadIII:
  272.    fldpi
  273.    fsubr
  274.    fchs
  275.  
  276. StoreZX:
  277.    mov   bx, z
  278.    fstp  QWORD PTR [bx+8]        ; <empty>
  279.    ret
  280. FPUcplxlog     ENDP
  281.  
  282.  
  283.  
  284.  
  285. FPUsinhcosh    PROC     x:word, sinh:word, cosh:word
  286. LOCAL Control:word
  287.    fstcw Control
  288.    push  Control                       ; Save control word on the stack
  289.    or    Control, 0000110000000000b
  290.    fldcw Control                       ; Set control to round towards zero
  291.  
  292.    mov   Sign, 0              ; Assume the sign is positive
  293.    mov   bx, x
  294.  
  295.    fldln2                     ; ln(2)
  296.    fdivr QWORD PTR [bx]       ; x/ln(2)
  297.  
  298.    cmp   BYTE PTR [bx+7], 0
  299.    jns   DuplicateX
  300.  
  301.    fchs                       ; x = |x|
  302.  
  303. DuplicateX:
  304.    fld   st                   ; x/ln(2), x/ln(2)
  305.    frndint                    ; int = integer(|x|/ln(2)), x/ln(2)
  306.    fxch                       ; x/ln(2), int
  307.    fsub  st, st(1)            ; rem < 1.0, int
  308.    fdiv  _2_                  ; rem/2 < 0.5, int
  309.    f2xm1                      ; (2**rem/2)-1, int
  310.    fadd  _1_                  ; 2**rem/2, int
  311.    fmul  st, st               ; 2**rem, int
  312.    fscale                     ; e**|x|, int
  313.    fstp  st(1)                ; e**|x|
  314.  
  315.    cmp   BYTE PTR [bx+7], 0
  316.    jns   ExitFexp
  317.  
  318.    fdivr _1_                  ; e**x      
  319.  
  320. ExitFexp:
  321.    fld   st                   ; e**x, e**x
  322.    fdivr PointFive            ; e**-x/2, e**x
  323.    fld   st                   ; e**-x/2, e**-x/2, e**x
  324.    fxch  st(2)                ; e**x, e**-x/2, e**-x/2
  325.    fdiv  _2_                  ; e**x/2,  e**-x/2, e**-x/2
  326.    fadd  st(2), st            ; e**x/2,  e**-x/2, cosh(x)
  327.    fsubr                      ; sinh(x), cosh(x)
  328.  
  329.    mov   bx, sinh             ; sinh, cosh
  330.    fstp  QWORD PTR [bx]       ; cosh
  331.    mov   bx, cosh
  332.    fstp  QWORD PTR [bx]       ; <empty>
  333.  
  334.    pop   Control
  335.    fldcw Control              ; Restore control word
  336.    ret
  337. FPUsinhcosh    ENDP
  338.  
  339.  
  340. FPUsincos  PROC  x:word, sinx:word, cosx:word
  341. LOCAL Status:word
  342.    mov   bx, x
  343.    fld   QWORD PTR [bx]       ; x
  344.  
  345.    cmp   fpu, 387
  346.    jne   Use387FPUsincos
  347.  
  348.    call  _Loaded387sincos     ; cos(x), sin(x)
  349.    mov   bx, cosx
  350.    fstp  QWORD PTR [bx]       ; sin(x)
  351.    mov   bx, sinx
  352.    fstp  QWORD PTR [bx]       ; <empty>
  353.    ret
  354.  
  355. Use387FPUsincos:
  356.  
  357.    sub   sp, 8                ; save 'x' on the CPU stack
  358.    mov   bx, sp
  359.    fstp  QWORD PTR [bx]       ; FPU stack:  <empty>
  360.  
  361.    call  cos
  362.  
  363.    add   sp, 8                ; take 'cos(x)' off the CPU stack
  364.    mov   bx, ax
  365.    cmp   compiled_by_turboc,0
  366.    jne   turbo_c1
  367.  
  368.    fld   QWORD PTR [bx]       ; FPU stack:  cos(x)
  369.  
  370. turbo_c1:
  371.    fld   st                   ; FPU stack:  cos(x), cos(x)
  372.    fmul  st, st               ; cos(x)**2, cos(x)
  373.    fsubr _1_                  ; sin(x)**2, cos(x)
  374.    fsqrt                      ; +/-sin(x), cos(x)
  375.  
  376.    mov   bx, x
  377.    fld   QWORD PTR [bx]       ; x, +/-sin(x), cos(x)
  378.    fldpi                      ; Pi, x, +/-sin(x), cos(x)
  379.    fadd  st, st               ; 2Pi, x, +/-sin(x), cos(x)
  380.    fxch                       ; |x|, 2Pi, +/-sin(x), cos(x)
  381.    fprem                      ; Angle, 2Pi, +/-sin(x), cos(x)
  382.    fstp  st(1)                ; Angle, +/-sin(x), cos(x)
  383.    fldpi                      ; Pi, Angle, +/-sin(x), cos(x)
  384.  
  385.    cmp   BYTE PTR [bx+7], 0
  386.    jns   SignAlignedPi
  387.  
  388.    fchs                       ; -Pi, Angle, +/-sin(x), cos(x)
  389.  
  390. SignAlignedPi:
  391.    fcompp                     ; +/-sin(x), cos(x)
  392.    fstsw Status               ; +/-sin(x), cos(x)
  393.  
  394.    mov   ax, Status
  395.    and   ah, 1
  396.    jz    StoreSinCos          ; Angle <= Pi
  397.  
  398.    fchs                       ; sin(x), cos(x)
  399.  
  400. StoreSinCos:
  401.    mov   bx, sinx
  402.    fstp  QWORD PTR [bx]       ; cos(x)
  403.    mov   bx, cosx
  404.    fstp  QWORD PTR [bx]       ; <empty>
  405.    ret
  406. FPUsincos   ENDP
  407.  
  408.  
  409. PUBLIC r16Mul
  410. r16Mul     PROC    uses si di, x1:word, x2:word, y1:word, y2:word
  411.       mov   si, x1
  412.       mov   bx, x2
  413.       mov   di, y1
  414.       mov   cx, y2
  415.  
  416.       xor   ax, ax
  417.       shl   bx, 1
  418.       jz    Exitr16Mult          ; Destination is zero
  419.  
  420.       rcl   ah, 1
  421.       shl   cx, 1
  422.       jnz   Chkr16Exp
  423.       xor   bx, bx               ; Source is zero
  424.       xor   si, si
  425.       jmp   Exitr16Mult
  426.  
  427.    Chkr16Exp:
  428.       rcl   al, 1
  429.       xor   ah, al               ; Resulting sign in ah
  430.       stc                        ; Put 'one' bit back into number
  431.       rcr   bl, 1
  432.       stc
  433.       rcr   cl, 1
  434.  
  435.       sub   ch, 127              ; Determine resulting exponent
  436.       add   bh, ch
  437.       mov   al, bh
  438.       mov   fake_es, ax          ; es has the resulting exponent and sign
  439.  
  440.       mov   ax, di
  441.       mov   al, ah
  442.       mov   ah, cl
  443.  
  444.       mov   dx, si
  445.       mov   dl, dh
  446.       mov   dh, bl
  447.  
  448.       mul   dx
  449.       mov   cx, fake_es
  450.  
  451.       shl   ax, 1
  452.       rcl   dx, 1
  453.       jnc   Remr16MulOneBit      ; 'One' bit is the next bit over
  454.  
  455.       inc   cl                   ; 'One' bit removed with previous shift
  456.       jmp   Afterr16MulNorm
  457.  
  458.    Remr16MulOneBit:
  459.       shl   ax, 1
  460.       rcl   dx, 1
  461.  
  462.    Afterr16MulNorm:
  463.       mov   bl, dh               ; Perform remaining 8 bit shift
  464.       mov   dh, dl
  465.       mov   dl, ah
  466.       mov   si, dx
  467.       mov   bh, cl               ; Put in the exponent
  468.       rcr   ch, 1                ; Get the sign
  469.       rcr   bx, 1                ; Normalize the result
  470.       rcr   si, 1
  471.    Exitr16Mult:
  472.       mov   ax, si
  473.       mov   dx, bx
  474.       ret
  475. r16Mul      ENDP
  476.  
  477.  
  478. PUBLIC RegFloat2Fg
  479. RegFloat2Fg     PROC    x1:word, x2:word, Fudge:word
  480.       mov   ax, WORD PTR x1
  481.       mov   dx, WORD PTR x2
  482.       mov   bx, ax
  483.       or    bx, dx
  484.       jz    ExitRegFloat2Fg
  485.  
  486.       xor   bx, bx
  487.       mov   cx, bx
  488.  
  489.       shl   ax, 1
  490.       rcl   dx, 1
  491.       rcl   bx, 1                   ; bx contains the sign
  492.  
  493.       xchg  cl, dh                  ; cx contains the exponent
  494.  
  495.       stc                           ; Put in the One bit
  496.       rcr   dl, 1
  497.       rcr   ax, 1
  498.  
  499.       sub   cx, 127 + 23
  500.       add   cx, Fudge
  501.       jz    ChkFgSign
  502.       jns   ShiftFgLeft
  503.  
  504.       neg   cx
  505.    ShiftFgRight:
  506.       shr   dx, 1
  507.       rcr   ax, 1
  508.       loop  ShiftFgRight
  509.       jmp   ChkFgSign
  510.  
  511.    ShiftFgLeft:
  512.       shl   ax, 1
  513.       rcl   dx, 1
  514.       loop  ShiftFgLeft
  515.  
  516.    ChkFgSign:
  517.       or    bx, bx
  518.       jz    ExitRegFloat2Fg
  519.  
  520.       not   ax
  521.       not   dx
  522.       add   ax, 1
  523.       adc   dx, 0
  524.  
  525.    ExitRegFloat2Fg:
  526.       ret
  527. RegFloat2Fg    ENDP
  528.  
  529.  
  530.  
  531. PUBLIC RegFg2Float
  532. RegFg2Float     PROC   x1:word, x2:word, FudgeFact:byte
  533.       mov   ax, x1
  534.       mov   dx, x2
  535.  
  536.       mov   cx, ax
  537.       or    cx, dx
  538.       jz    ExitFudgedToRegFloat
  539.  
  540.       mov   ch, 127 + 32
  541.       sub   ch, FudgeFact
  542.       xor   cl, cl
  543.       shl   ax, 1       ; Get the sign bit
  544.       rcl   dx, 1
  545.       jnc   FindOneBit
  546.  
  547.       inc   cl          ; Fudged < 0, convert to postive
  548.       not   ax
  549.       not   dx
  550.       add   ax, 1
  551.       adc   dx, 0
  552.  
  553.    FindOneBit:
  554.       shl   ax, 1
  555.       rcl   dx, 1
  556.       dec   ch
  557.       jnc   FindOneBit
  558.       dec   ch
  559.  
  560.       mov   al, ah
  561.       mov   ah, dl
  562.       mov   dl, dh
  563.       mov   dh, ch
  564.  
  565.       shr   cl, 1       ; Put sign bit in
  566.       rcr   dx, 1
  567.       rcr   ax, 1
  568.  
  569.    ExitFudgedToRegFloat:
  570.       ret
  571. RegFg2Float      ENDP
  572.  
  573.  
  574. PUBLIC ExpFudged
  575. ExpFudged      PROC    uses si, x_low:word, x_high:word, Fudge:word
  576. LOCAL exp:WORD
  577.       xor   ax, ax
  578.       mov   WORD PTR Ans, ax
  579.       mov   WORD PTR Ans + 2, ax
  580.       mov   ax, WORD PTR x_low
  581.       mov   dx, WORD PTR x_high
  582.       or    dx, dx
  583.       js    NegativeExp
  584.  
  585.       div   Ln2Fg16
  586.       mov   exp, ax
  587.       or    dx, dx
  588.       jz    Raiseexp
  589.  
  590.       mov   ax, dx
  591.       mov   si, dx
  592.       mov   bx, 1
  593.  
  594.    PosExpLoop:
  595.       add   WORD PTR Ans, ax
  596.       adc   WORD PTR Ans + 2, 0
  597.       inc   bx
  598.       mul   si
  599.       mov   ax, dx
  600.       xor   dx, dx
  601.       div   bx
  602.       or    ax, ax
  603.       jnz   PosExpLoop
  604.  
  605.    Raiseexp:
  606.       inc   WORD PTR Ans + 2
  607.       mov   ax, WORD PTR Ans
  608.       mov   dx, WORD PTR Ans + 2
  609.       mov   cx, -16
  610.       add   cx, Fudge
  611.       add   cx, exp
  612.       or    cx, cx
  613.       jz    ExitExpFudged
  614.       jns   LeftShift
  615.       neg   cx
  616.  
  617.    RightShift:
  618.       shr   dx, 1
  619.       rcr   ax, 1
  620.       loop  RightShift
  621.       jmp   ExitExpFudged
  622.  
  623.    NegativeExp:
  624.       not   ax
  625.       not   dx
  626.       add   ax, 1
  627.       adc   dx, 0
  628.       div   Ln2Fg16
  629.       neg   ax
  630.       mov   exp, ax
  631.  
  632.       or    dx, dx
  633.       jz    Raiseexp
  634.  
  635.       mov   ax, dx
  636.       mov   si, dx
  637.       mov   bx, 1
  638.  
  639.    NegExpLoop:
  640.       sub   WORD PTR Ans, ax
  641.       sbb   WORD PTR Ans + 2, 0
  642.       inc   bx
  643.       mul   si
  644.       mov   ax, dx
  645.       xor   dx, dx
  646.       div   bx
  647.       or    ax, ax
  648.       jz    Raiseexp
  649.  
  650.       add   WORD PTR Ans, ax
  651.       adc   WORD PTR Ans + 2, 0
  652.       inc   bx
  653.       mul   si
  654.       mov   ax, dx
  655.       xor   dx, dx
  656.       div   bx
  657.       or    ax, ax
  658.       jnz   NegExpLoop
  659.       jmp   Raiseexp
  660.  
  661.    LeftShift:
  662.       shl   ax, 1
  663.       rcl   dx, 1
  664.       loop  LeftShift
  665.  
  666.    ExitExpFudged:
  667.       ret
  668. ExpFudged      ENDP
  669.  
  670.  
  671.  
  672. PUBLIC   LogFudged
  673. LogFudged      PROC    uses si di, x_low:word, x_high:word, Fudge:word
  674. LOCAL exp:WORD
  675.       xor   bx, bx
  676.       mov   cx, 16
  677.       sub   cx, Fudge
  678.       mov   ax, x_low
  679.       mov   dx, x_high
  680.  
  681.       or    dx, dx
  682.       jz    ChkLowWord
  683.  
  684.    Incexp:
  685.       shr   dx, 1
  686.       jz    DetermineOper
  687.       rcr   ax, 1
  688.       inc   cx
  689.       jmp   Incexp
  690.  
  691.    ChkLowWord:
  692.       or    ax, ax
  693.       jnz   Decexp
  694.       jmp   ExitLogFudged
  695.  
  696.    Decexp:
  697.       dec   cx                      ; Determine power of two
  698.       shl   ax, 1
  699.       jnc   Decexp
  700.  
  701.    DetermineOper:
  702.       mov   exp, cx
  703.       mov   si, ax                  ; si =: x + 1
  704.       shr   si, 1
  705.       stc
  706.       rcr   si, 1
  707.       mov   dx, ax
  708.       xor   ax, ax
  709.       shr   dx, 1
  710.       rcr   ax, 1
  711.       shr   dx, 1
  712.       rcr   ax, 1                   ; dx:ax = x - 1
  713.       div   si
  714.  
  715.       mov   bx, ax                  ; ax, Fudged 16, max of 0.3333333
  716.       shl   ax, 1                   ; x = (x - 1) / (x + 1), Fudged 16
  717.       mul   ax
  718.       shl   ax, 1
  719.       rcl   dx, 1
  720.       mov   ax, dx                  ; dx:ax, Fudged 35, max = 0.1111111
  721.       mov   si, ax                  ; si = (ax * ax), Fudged 19
  722.  
  723.       mov   ax, bx
  724.    ; bx is the accumulator, First term is x
  725.       mul   si                      ; dx:ax, Fudged 35, max of 0.037037
  726.       mov   fake_es, dx             ; Save high word, Fudged (35 - 16) = 19
  727.       mov   di, 0c000h              ; di, 3 Fudged 14
  728.       div   di                      ; ax, Fudged (36 - 14) = 21
  729.       or    ax, ax
  730.       jz    Addexp
  731.  
  732.       mov   cl, 5
  733.       shr   ax, cl
  734.       add   bx, ax                  ; bx, max of 0.345679
  735.    ; x = x + x**3/3
  736.  
  737.       mov   ax, fake_es             ; ax, Fudged 19
  738.       mul   si                      ; dx:ax, Fudged 38, max of 0.004115
  739.       mov   fake_es, dx             ; Save high word, Fudged (38 - 16) = 22
  740.       mov   di, 0a000h              ; di, 5 Fudged 13
  741.       div   di                      ; ax, Fudged (38 - 13) = 25
  742.       or    ax, ax
  743.       jz    Addexp
  744.  
  745.       mov   cl, 9
  746.       shr   ax, cl
  747.       add   bx, ax
  748.    ; x = x + x**3/3 + x**5/5
  749.  
  750.       mov   ax, fake_es             ; ax, Fudged 22
  751.       mul   si                      ; dx:ax, Fudged 41, max of 0.0004572
  752.       mov   di, 0e000h              ; di, 7 Fudged 13
  753.       div   di                      ; ax, Fudged (41 - 13) = 28
  754.       mov   cl, 12
  755.       shr   ax, cl
  756.       add   bx, ax
  757.  
  758.    Addexp:
  759.       shl   bx, 1                   ; bx *= 2, Fudged 16, max of 0.693147
  760.    ; x = 2 * (x + x**3/3 + x**5/5 + x**7/7)
  761.       mov   cx, exp
  762.       mov   ax, Ln2Fg16            ; Answer += exp * Ln2Fg16
  763.       or    cx, cx
  764.       js    SubFromAns
  765.  
  766.       mul   cx
  767.       add   ax, bx
  768.       adc   dx, 0
  769.       jmp   ExitLogFudged
  770.  
  771.    SubFromAns:
  772.       neg   cx
  773.       mul   cx
  774.       xor   cx, cx
  775.       xchg  cx, dx
  776.       xchg  bx, ax
  777.       sub   ax, bx
  778.       sbb   dx, cx
  779.  
  780.    ExitLogFudged:
  781.    ; x = 2 * (x + x**3/3 + x**5/5 + x**7/7) + (exp * Ln2Fg16)
  782.       ret
  783. LogFudged      ENDP
  784.  
  785.  
  786.  
  787.  
  788. PUBLIC LogFloat14
  789. LogFloat14     PROC     x1:word, x2:word
  790.       mov   ax, WORD PTR x1
  791.       mov   dx, WORD PTR x2
  792.       shl   ax, 1
  793.       rcl   dx, 1
  794.       xor   cx, cx
  795.       xchg  cl, dh
  796.  
  797.       stc
  798.         rcr   dl, 1
  799.         rcr   ax, 1
  800.  
  801.       sub   cx, 127 + 23
  802.       neg   cx
  803.       push  cx
  804.       push  dx
  805.       push  ax
  806.       call  LogFudged
  807.       add   sp, 6
  808.       ret
  809. LogFloat14     ENDP
  810.  
  811.  
  812. PUBLIC RegSftFloat
  813. RegSftFloat     PROC   x1:word, x2:word, Shift:byte
  814.       mov   ax, x1
  815.       mov   dx, x2
  816.  
  817.       shl   dx, 1
  818.       rcl   cl, 1
  819.  
  820.       add   dh, Shift
  821.  
  822.       shr   cl, 1
  823.       rcr   dx, 1
  824.  
  825.       ret
  826. RegSftFloat      ENDP
  827.  
  828.  
  829.  
  830.  
  831. PUBLIC RegDivFloat
  832. RegDivFloat     PROC  uses si di, x1:word, x2:word, y1:word, y2:word
  833.       mov   si, x1
  834.       mov   bx, x2
  835.       mov   di, y1
  836.       mov   cx, y2
  837.  
  838.       xor   ax, ax
  839.       shl   bx, 1
  840.       jnz   ChkOtherOp
  841.       jmp   ExitRegDiv           ; Destination is zero
  842.  
  843.    ChkOtherOp:
  844.       rcl   ah, 1
  845.       shl   cx, 1
  846.       jnz   ChkDivExp
  847.       xor   bx, bx               ; Source is zero
  848.       xor   si, si
  849.       jmp   ExitRegDiv
  850.  
  851.    ChkDivExp:
  852.       rcl   al, 1
  853.       xor   ah, al               ; Resulting sign in ah
  854.       stc                        ; Put 'one' bit back into number
  855.       rcr   bl, 1
  856.       stc
  857.       rcr   cl, 1
  858.  
  859.       sub   ch, 127              ; Determine resulting exponent
  860.       sub   bh, ch
  861.       mov   al, bh
  862.       mov   fake_es, ax          ; es has the resulting exponent and sign
  863.  
  864.       mov   ax, si               ; 8 bit shift, bx:si moved to dx:ax
  865.       mov   dh, bl
  866.       mov   dl, ah
  867.       mov   ah, al
  868.       xor   al, al
  869.  
  870.       mov   bh, cl               ; 8 bit shift, cx:di moved to bx:cx
  871.       mov   cx, di
  872.       mov   bl, ch
  873.       mov   ch, cl
  874.       xor   cl, cl
  875.  
  876.       shr   dx, 1
  877.       rcr   ax, 1
  878.  
  879.       div   bx
  880.       mov   si, dx               ; Save (and shift) remainder
  881.       mov   dx, cx               ; Save the quess
  882.       mov   cx, ax
  883.       mul   dx                   ; Mult quess times low word
  884.       xor   di, di
  885.       sub   di, ax               ; Determine remainder
  886.       sbb   si, dx
  887.       mov   ax, di
  888.       mov   dx, si
  889.       jc    RemainderNeg
  890.  
  891.       xor   di, di
  892.       jmp   GetNextDigit
  893.  
  894.    RemainderNeg:
  895.       mov   di, 1                ; Flag digit as negative
  896.       not   ax                   ; Convert remainder to positive
  897.       not   dx
  898.       add   ax, 1
  899.       adc   dx, 0
  900.  
  901.    GetNextDigit:
  902.       shr   dx, 1
  903.       rcr   ax, 1
  904.       div   bx
  905.       xor   bx, bx
  906.       shl   dx, 1
  907.       rcl   ax, 1
  908.       rcl   bl, 1                ; Save high bit
  909.  
  910.       mov   dx, cx               ; Retrieve first digit
  911.       or    di, di
  912.       jz    RemoveDivOneBit
  913.  
  914.       neg   ax                   ; Digit was negative
  915.       neg   bx
  916.       dec   dx
  917.  
  918.    RemoveDivOneBit:
  919.       add   dx, bx
  920.       mov   cx, fake_es
  921.       shl   ax, 1
  922.       rcl   dx, 1
  923.       jc    AfterDivNorm
  924.  
  925.       dec   cl
  926.       shl   ax, 1
  927.       rcl   dx, 1
  928.  
  929.    AfterDivNorm:
  930.       mov   bl, dh               ; Perform remaining 8 bit shift
  931.       mov   dh, dl
  932.       mov   dl, ah
  933.       mov   si, dx
  934.       mov   bh, cl               ; Put in the exponent
  935.       shr   ch, 1                ; Get the sign
  936.       rcr   bx, 1                ; Normalize the result
  937.       rcr   si, 1
  938.  
  939.    ExitRegDiv:
  940.       mov   ax, si
  941.       mov   dx, bx
  942.       ret
  943. RegDivFloat      ENDP
  944.  
  945.  
  946.  
  947. Term        equ      <ax>
  948. Num         equ      <bx>
  949. Factorial   equ      <cx>
  950. Sin         equ      <si>
  951. Cos         equ      <di>
  952. e           equ      <si>
  953. Inve        equ      <di>
  954.          
  955. SinCos086   PROC     uses si di, LoNum:WORD, HiNum:WORD, SinAddr:WORD, \
  956.                                 CosAddr:WORD
  957.    mov   ax, LoNum 
  958.    mov   dx, HiNum
  959.    
  960.    xor   cx, cx
  961. ;   mov   SinNeg, cx    ;CJLT - not needed now
  962. ;   mov   CosNeg, cx     ;CJLT - not needed now
  963.    mov   a, cx        ;CJLT - Not needed by the original code, but it
  964.                ;       is now!
  965.    or    dx, dx
  966.    jns   AnglePositive
  967.    
  968.    not   ax
  969.    not   dx
  970.    add   ax, 1
  971.    adc   dx, cx        ;conveniently zero
  972.    mov   a,8        ;a now has 4 bits: Sign+quadrant+octant
  973.       
  974. AnglePositive:
  975.    mov   si, ax
  976.    mov   di, dx
  977.    mul   WORD PTR InvPiFg33
  978.    mov   bx, dx
  979.    mov   ax, di
  980.    mul   WORD PTR InvPiFg33
  981.    add   bx, ax
  982.    adc   cx, dx
  983.    mov   ax, si
  984.    mul   WORD PTR InvPiFg33 + 2
  985.    add   bx, ax
  986.    adc   cx, dx
  987.    mov   ax, di
  988.    mul   WORD PTR InvPiFg33 + 2
  989.    add   ax, cx
  990.    adc   dx, 0
  991.  
  992.    and   dx, 3    ;Remove multiples of 2 pi
  993.    shl   dx, 1  ;move over to make space for octant number
  994. ;
  995. ;CJLT - new code to reduce angle to:  0 <= angle <= 45
  996. ;
  997.    or    ax, ax
  998.    jns   Lessthan45
  999.    inc   dx    ;octant number
  1000.    not   ax    ;angle=90-angle if it was >45 degrees
  1001. Lessthan45:
  1002.    add   a,  dx    ;remember octant and Sign in a
  1003.    mov   Num, ax ;ax=Term, now
  1004. ;
  1005. ; We do the Taylor series with all numbers scaled by pi/2
  1006. ; so InvPiFg33 represents one. Truly.
  1007. ;
  1008.    mov   Factorial, WORD PTR InvPiFg33 + 2
  1009.    mov   one, Factorial
  1010.    mov   Cos, Factorial          ; Cos = 1
  1011.    mov   Sin, Num                ; Sin = Num
  1012.       
  1013. LoopIntSinCos:
  1014.    TaylorTerm                    ; ax=Term = Num * (Num/2) * (Num/3) * . . .
  1015.    sub   Cos, Term               ; Cos = 1 - Num*(Num/2) + (Num**4)/4! - . . .
  1016.    cmp   Term, WORD PTR TrigLimit
  1017.    jbe   SHORT ExitIntSinCos
  1018.  
  1019.    TaylorTerm
  1020.    sub   Sin, Term               ; Sin = Num - Num*(Num/2)*(Num/3) + (Num**5)/5! - . . .
  1021.    cmp   Term, WORD PTR TrigLimit
  1022.    jbe   SHORT ExitIntSinCos
  1023.  
  1024.    TaylorTerm
  1025.    add   Cos, Term
  1026.    cmp   Term, WORD PTR TrigLimit
  1027.    jbe   SHORT ExitIntSinCos
  1028.  
  1029.    TaylorTerm                    ; Term = Num * (x/2) * (x/3) * . . .
  1030.    add   Sin, Term
  1031.    cmp   Term, WORD PTR TrigLimit
  1032.    jnbe  LoopIntSinCos
  1033.       
  1034. ExitIntSinCos:
  1035.    xor   ax, ax
  1036.    mov   cx, ax
  1037.    cmp   Cos, WORD PTR InvPiFg33 + 2
  1038.    jb    CosDivide               ; Cos < 1.0
  1039.       
  1040.    inc   cx                      ; Cos == 1.0
  1041.    jmp   StoreCos
  1042.  
  1043. CosDivide:
  1044.    mov   dx, Cos
  1045.    div   WORD PTR InvPiFg33 + 2
  1046.       
  1047. StoreCos:
  1048.    mov   Cos, ax                 ; cx:Cos
  1049.  
  1050.    xor   ax, ax
  1051.    mov   bx, ax
  1052.    cmp   Sin, WORD PTR InvPiFg33 + 2
  1053.    jb    SinDivide               ; Sin < 1.0
  1054.    
  1055.    inc   bx                      ; Sin == 1.0
  1056.    jmp   StoreSin
  1057.       
  1058. SinDivide:
  1059.    mov   dx, Sin
  1060.    div   WORD PTR InvPiFg33 + 2
  1061.       
  1062. StoreSin:
  1063.    mov   Sin, ax                 ; bx:Sin
  1064. ; CJLT again. New tests are needed to correct signs and exchange sin/cos values
  1065.    mov   ax, a
  1066.    inc   al    ;forces bit 1 to xor of previous bits 0 and 1
  1067.    test  al, 2
  1068.    jz    ChkNegCos
  1069.  
  1070.    xchg  cx, bx
  1071.    xchg  Sin, Cos
  1072. ;   mov   ax, SinNeg    commented out by CJLT. This was a bug.
  1073. ;   xchg  ax, CosNeg
  1074. ;   mov   CosNeg, ax    and this was meant to be  mov  SinNeg,ax
  1075.  
  1076. ChkNegCos:
  1077.    inc   al    ;forces bit 2 to xor of original bits 1 and 2
  1078.    test  al, 4 
  1079.    jz    ChkNegSin
  1080.  
  1081.    not   Cos    ;negate cos if quadrant 2 or 3
  1082.    not   cx
  1083.    add   Cos, 1
  1084.    adc   cx, 0
  1085.  
  1086. ChkNegSin:
  1087.    inc   al
  1088.    inc   al    ;forces bit 3 to xor of original bits 2 and 3
  1089.    test  al, 8
  1090.    jz    CorrectQuad
  1091.  
  1092.    not   Sin
  1093.    not   bx
  1094.    add   Sin, 1
  1095.    adc   bx, 0
  1096.  
  1097. CorrectQuad:
  1098.  
  1099. CosPolarized:     
  1100.    mov   dx, bx
  1101.    mov   bx, CosAddr
  1102.    mov   WORD PTR [bx], Cos
  1103.    mov   WORD PTR [bx+2], cx
  1104.  
  1105. SinPolarized:
  1106.    mov   bx, SinAddr
  1107.    mov   WORD PTR [bx], Sin
  1108.    mov   WORD PTR [bx+2], dx
  1109.    ret
  1110. SinCos086      ENDP
  1111.       
  1112.  
  1113. PUBLIC ArcTan086
  1114. ;
  1115. ;Used to calculate logs of complex numbers, since log(R,theta)=log(R)+i.theta
  1116. ; in polar coordinates.
  1117. ;
  1118. ;In C we need the prototype:
  1119. ;long ArcTan086(long, long)
  1120.  
  1121. ;The parameters are x and y, the returned value arctan(y/x) in the range 0..2pi.
  1122. ArcTan086     PROC  uses si di, x1:word, x2:word, y1:word, y2:word
  1123.       xor   ax, ax ;ax=0
  1124.       mov   si, x1 ;Lo
  1125.       mov   bx, x2 ;Hi
  1126.       or    bx, bx ;Sign set ?
  1127.       jns   xplus
  1128.       inc   ax
  1129.       not   si
  1130.       not   bx
  1131.       add   bx, 1
  1132.       adc   si, 0    ;We have abs(x) now
  1133.  xplus:           
  1134.       mov   di, y1 ;Lo
  1135.       mov   cx, y2 ;Hi
  1136.       or    cx, cx ;Sign set?
  1137.       jns   yplus
  1138.       inc   ax
  1139.       inc   ax       ;Set bit 1 of ax
  1140.       shl   ax, 1  ; and shift it all left 
  1141.       not  di
  1142.       not   cx
  1143.       add   di, 1
  1144.       adc   cx, 0  ;We have abs(y) now
  1145. yplus:
  1146.       cmp   bx, cx    ;y>x?
  1147.       jl    no_xchg
  1148.       jg    xchg_xy
  1149.       cmp   si, di    ;Hi words zero. What about lo words?
  1150.       jle   no_xchg
  1151. xchg_xy:        ;Exchange them
  1152.       inc   ax        ;Flag the exchange
  1153.       xchg  si, di
  1154.       xchg  bx, cx
  1155. no_xchg:
  1156.       mov   SinNeg, ax    ;Remember signs of x and y, and whether exchanged
  1157.       or    cx, cx    ;y<x now, but is y>=1.0 ?      
  1158.       jz    ynorm    ;no, so continue
  1159. normy:            ;yes, normalise by reducing y to 16 bits max.
  1160.       rcr   cx, 1    ; (We don't really lose any precision)
  1161.       rcr   di, 1
  1162.       clc
  1163.       rcr   bx, 1
  1164.       rcr   si, 1
  1165.       or    cx, cx
  1166.       jnz   normy      
  1167. ynorm:
  1168.  
  1169.       ret
  1170. ArcTan086    ENDP
  1171.  
  1172. ;
  1173. ;There now follows Chris Lusby Taylor's novel (such modesty!) method
  1174. ;of calculating exp(x). Originally, I was going to do it by decomposing x
  1175. ;into a sum of terms of the form:
  1176. ;
  1177. ;  th            -i
  1178. ; i   term=ln(1+2  )
  1179. ;                                     -i
  1180. ;If x>term[i] we subtract term[i] from x and multiply the answer by 1 + 2
  1181. ;
  1182. ;We can multiply by that factor by shifting and adding. Neat eh!
  1183. ;
  1184. ;Unfortunately, however, for 16 bit accuracy, that method turns out to be
  1185. ;slower than what follows, which is also novel. Here, I first divide x not
  1186. ;by ln(2) but ln(2)/16 so that we can look up an initial answer in a table of
  1187. ;2^(n/16). This leaves the remainder so small that the polynomial Taylor series
  1188. ;converges in just 1+x+x^2/2 which is calculated as 1+x(1+x/2).
  1189. ;
  1190. _e2xLT   PROC        ;argument in dx.ax (bitshift=16 is hard coded here)
  1191.    or    dx, dx
  1192.    jns   CalcExpLT
  1193.       
  1194.    not   ax        ; if negative, calc exp(abs(x))
  1195.    not   dx
  1196.    add   ax, 1
  1197.    adc   dx, 0
  1198.    
  1199. CalcExpLT:
  1200.          shl   ax, 1
  1201.       rcl   dx, 1
  1202.       shl   ax, 1
  1203.       rcl   dx, 1
  1204.       shl   ax, 1
  1205.       rcl   dx, 1        ;x is now in fg19 form for accuracy
  1206.                 ; so, relative to fg16, we have:
  1207.    div   Ln2Fg15        ; 8x==(a * Ln(2)/2) + Rem
  1208.                    ;  x=(a * Ln(2)/16) + Rem/8
  1209.                    ;so exp(x)=exp((a * Ln(2)/16) + Rem/8)
  1210.                 ;         =exp(a/16 * Ln(2)) * exp(Rem/8)
  1211.                 ;         =2^(a/16) * exp(Rem)
  1212.                 ;a mod 16 will give us an initial estimate 
  1213.    mov  cl, 4
  1214.    mov  di, ax            ;Remember original
  1215.    shr  ax, cl        
  1216.    mov   a, ax            ;a/16 will give us a bit shift
  1217.    mov  ax, di
  1218.    and  ax, 0000fh        ;a mod 16
  1219.    shl  ax, 1            ;used as an index into 2 byte per element Table
  1220.    mov  di, ax
  1221.    dec  cx            ;3, please
  1222.    add   dx, 4            ;to control rounding up/down
  1223.    shr   dx, cl            ;Num=Rem/8 (convert back to fg16)
  1224.                 ; 
  1225.    mov   ax, dx
  1226.    shr   ax, 1             ;Num/2  fg 16
  1227.    inc   ax            ;rounding control
  1228.    stc
  1229.    rcr   ax, 1            ;1+Num/2   fg15
  1230.    mul   dx            ;dx:ax=Num(1+Num/2) fg31, so dx alone is fg15
  1231.    shl   ax, 1            ;more rounding control
  1232.    adc   dx, 8000H         ;dx=1+Num(1+Num/2) fg15
  1233.    mov   ax, Table[di]        ;Get table entry fg15
  1234.    mul   dx            ;Only two multiplys used!  fg14, now (15+15-16)
  1235.    shl   ax, 1
  1236.    rcl   dx, 1            ;fg15
  1237.    mov   e,  dx 
  1238.    ret                          ; return e=e**x * (2**15), 1 < e**x < 2
  1239. _e2xLT   ENDP            ;        a= bitshift needed 
  1240.  
  1241.  
  1242.       
  1243. Exp086    PROC     uses si di, LoNum:WORD, HiNum:WORD
  1244.    mov   ax, LoNum 
  1245.    mov   dx, HiNum
  1246.    mov   TrigOverflow, 0
  1247.    
  1248.     call  _e2xLT    ;Use Chris Lusby Taylor's e2x
  1249.  
  1250.    cmp   a, 15        ;CJLT - was 16
  1251.    jae   Overflow
  1252.       
  1253. ;   cmp   expSign, 0
  1254. ;   jnz   NegNumber
  1255.    cmp   HiNum, 0    ;CJLT - we don't really need expSign
  1256.    jl   NegNumber
  1257.       
  1258.    mov   ax, e
  1259.    mov   dx, ax
  1260.    inc   a
  1261.    mov   cx, 16
  1262.    sub   cx, a
  1263.    shr   dx, cl
  1264.    mov   cx, a
  1265.    shl   ax, cl
  1266.    jmp   ExitExp086
  1267.       
  1268. Overflow:
  1269.    xor   ax, ax
  1270.    xor   dx, dx
  1271.    mov   TrigOverflow, 1
  1272.    jmp   ExitExp086
  1273.       
  1274. NegNumber:
  1275.    cmp   e, 8000h
  1276.    jne   DivideE
  1277.       
  1278.    mov   ax, e
  1279.    dec   a
  1280.    jmp   ShiftE
  1281.       
  1282. DivideE:
  1283.    xor   ax, ax
  1284.    mov   dx, ax
  1285.    stc
  1286.    rcr   dx, 1
  1287.    div   e
  1288.  
  1289. ShiftE:
  1290.    xor   dx, dx
  1291.    mov   cx, a
  1292.    shr   ax, cl
  1293.       
  1294. ExitExp086:
  1295.    ret
  1296. Exp086    ENDP
  1297.  
  1298.  
  1299.  
  1300. SinhCosh086    PROC     uses si di, LoNum:WORD, HiNum:WORD, SinhAddr:WORD, \
  1301.                                    CoshAddr:WORD
  1302.    mov   ax, LoNum
  1303.    mov   dx, HiNum
  1304.  
  1305.    call  _e2xLT        ;calculate exp(|x|) fg 15
  1306.             ;answer is e*2^a
  1307.    cmp   e, 8000h    ;e==1 ?    
  1308.    jne   InvertE        ; e > 1, so we can invert it.
  1309.  
  1310.    mov   dx, 1
  1311.    xor   ax, ax
  1312.    cmp   a, 0
  1313.    jne   Shiftone
  1314.  
  1315.    mov   e, ax
  1316.    mov   cx, ax
  1317.    jmp   ChkSinhSign
  1318.  
  1319. Shiftone:
  1320.    mov   cx, a
  1321.    shl   dx, cl
  1322.    dec   cx
  1323.    shr   e, cl
  1324.    shr   dx, 1
  1325.    shr   e, 1
  1326.    mov   cx, dx
  1327.    sub   ax, e
  1328.    sbb   dx, 0
  1329.    xchg  ax, e
  1330.    xchg  dx, cx
  1331.    jmp   ChkSinhSign
  1332.  
  1333. InvertE:
  1334.    xor   ax, ax               ; calc 1/e
  1335.    mov   dx, 8000h
  1336.    div   e
  1337.  
  1338.    mov   Inve, ax
  1339.  
  1340. ShiftE:
  1341.    mov   cx, a
  1342.    shr   Inve, cl
  1343.    inc   cl
  1344.    mov   dx, e
  1345.    shl   e, cl
  1346.    neg   cl
  1347.    add   cl, 16
  1348.    shr   dx, cl
  1349.    mov   cx, dx               ; cx:e == e**Exp
  1350.  
  1351.    mov   ax, e                ; dx:e == e**Exp
  1352.    add   ax, Inve
  1353.    adc   dx, 0
  1354.    shr   dx, 1
  1355.    rcr   ax, 1                ; cosh(Num) = (e**Exp + 1/e**Exp) / 2
  1356.  
  1357.    sub   e, Inve
  1358.    sbb   cx, 0
  1359.    sar   cx, 1
  1360.    rcr   e, 1
  1361.  
  1362. ChkSinhSign:
  1363.    or    HiNum, 0
  1364.    jns   StoreHyperbolics
  1365.  
  1366.    not   e
  1367.    not   cx
  1368.    add   e, 1
  1369.    adc   cx, 0
  1370.  
  1371. StoreHyperbolics:
  1372.    mov   bx, CoshAddr
  1373.    mov   WORD PTR [bx], ax
  1374.    mov   WORD PTR [bx+2], dx
  1375.  
  1376.    mov   bx, SinhAddr
  1377.    mov   WORD PTR [bx], e
  1378.    mov   WORD PTR [bx+2], cx
  1379.  
  1380.    ret
  1381. SinhCosh086    ENDP
  1382.  
  1383.  
  1384.  
  1385. Log086   PROC     uses si di, LoNum:WORD, HiNum:WORD, Fudge:WORD
  1386. LOCAL Exp:WORD, Accum:WORD, LoAns:WORD, HiAns:WORD
  1387. ;NOTE: CJLT's method does not need LoAns, HiAns, but he hasn't yet
  1388. ;taken them out
  1389.       xor   bx, bx
  1390.       mov   cx, Fudge
  1391.       mov   ax, LoNum
  1392.       mov   dx, HiNum
  1393.       mov   TrigOverflow, 0
  1394.  
  1395.       or    dx, dx
  1396.       js    Overflow
  1397.       jnz   ShiftUp
  1398.  
  1399.       or    ax, ax
  1400.       jnz   ShiftUp      
  1401.  
  1402.    Overflow:
  1403.       mov   TrigOverflow, 1
  1404.       jmp   ExitLog086
  1405.  
  1406.    ShiftUp:
  1407.       inc   cx                      ; cx = Exp
  1408.       shl   ax, 1
  1409.       rcl   dx, 1
  1410.       or    dx, dx
  1411.       jns   ShiftUp        ;shift until dx in fg15 form
  1412.  
  1413.       neg   cx
  1414.       add   cx, 31
  1415.       mov   Exp, cx
  1416. ;CJLT method starts here. We try to reduce x to make it very close to 1
  1417. ;store LoAns in bx for now (fg 16; initially 0)
  1418.       mov  cl,2        ;shift count
  1419. redoterm2:
  1420.       cmp  dx, 0AAABH    ;x > 4/3 ?
  1421.       jb  doterm3
  1422.       mov  ax, dx
  1423.       shr  ax, cl
  1424.       sub  dx, ax    ;x:=x(1-1/4)
  1425.       add  bx, 49a5H    ;ln(4/3) fg 15
  1426.       jmp  redoterm2
  1427.  doterm3:     
  1428.       inc  cl        ;count=3
  1429. redoterm3:
  1430.       cmp  dx, 9249H    ;x > 8/7 ?
  1431.       jb  doterm4
  1432.       mov  ax, dx
  1433.       shr  ax, cl
  1434.       sub  dx, ax    ;x:=x(1-1/8)
  1435.       add  bx, 222eH    ;ln(8/7)
  1436.       jmp  redoterm3
  1437.  doterm4:
  1438.       inc  cl        ;count=4
  1439.       cmp  dx, 8889H    ;x > 16/15 ?
  1440.       jb  skipterm4
  1441.       mov  ax, dx
  1442.       shr  ax, cl
  1443.       sub  dx, ax    ;x:=x(1-1/16)
  1444.       add  bx, 1085h    ;ln(16/15)
  1445. ;No need to retry term4 as error is acceptably low if we ignore it
  1446. skipterm4:
  1447. ;Now we have reduced x to the range 1 <=x <1.072
  1448. ;
  1449. ;Now we continue with the conventional series, but x is so small we
  1450. ;can ignore all terms except the first!
  1451. ;i.e.:
  1452. ;ln(x)=2(x-1)/(x+1)
  1453.       sub   dx, 8000h        ; dx= x-1, fg 15
  1454.       mov   cx, dx
  1455.       stc    
  1456.       rcr   cx, 1        ; cx = 1 + (x-1)/2   fg 15
  1457.                       ;   = 1+x            fg 14
  1458.       mov   ax,4000H        ;rounding control (Trust me)
  1459.       div   cx            ;ax=ln(x)
  1460.       add   bx, ax        ;so add it to the rest of the Ans. No carry
  1461.    MultExp:
  1462.       mov   cx, Exp
  1463.       mov   ax, Ln2Fg16
  1464.       or    cx, cx
  1465.       js    SubFromAns
  1466.  
  1467.       mul   cx                      ; cx = Exp * Lg2Fg16, fg 16
  1468.       add   ax, bx        ;add bx part of answer
  1469.       adc   dx, 0
  1470.       jmp   ExitLog086
  1471.  
  1472.    SubFromAns:
  1473.       inc   bx        ;Somewhat artificial, but we need to add 1 somewhere
  1474.       neg   cx
  1475.       mul   cx
  1476.    not   ax
  1477.       not   dx
  1478.       add   ax, bx
  1479.       adc   dx, 0
  1480.  
  1481.    ExitLog086:
  1482.       ret
  1483. Log086   ENDP
  1484.  
  1485.  
  1486. END
  1487.